<script setup name="access">
import { ref } from "vue"
import { getRuleList, createRule, updateRule, updateRuleStatus, deleteRole } from "@/api/rule"
import { useInitTable, useInitForm } from "@/composables/useCommon"
import ListHeader from "@/components/ListHeader.vue"
import FormDialog from "@/components/FormDialog.vue"
import IconSelect from "@/components/IconSelect.vue"

const defaultExpandedKeys = ref([])
const options = ref([])
const { windowHeight, tableData, loading, getData, handleStatusChange, handleDelete } = useInitTable({
  getList: getRuleList,
  delete: deleteRole,
  updateStatus: updateRuleStatus,
  onGetList: res => {
    tableData.value = res.list
    ;(options.value = res.rules), (defaultExpandedKeys.value = res.list.map(o => o.id))
  }
})

// 解构表单公共方法
const { form, dialogRef, formRef, rules, dialogTitle, handleSubmit, handleCreate, handleEdit, resetForm } = useInitForm({
  getData,
  create: createRule,
  updata: updateRule,
  form: {
    rule_id: 0,
    menu: 0,
    name: "",
    condition: "",
    method: "GET",
    status: 1,
    order: 10,
    icon: "",
    frontpath: ""
  },
  rules: {
    rule_id: [{ required: true, message: "上级菜单不能为空", trigger: "blur" }],
    menu: [{ required: true }],
    name: [{ required: true, message: "菜单/权限名称不能为空", trigger: "blur" }],
    condition: [{ required: true, message: "后端规则不能为空", trigger: "blur" }],
    method: [{ required: true, message: "请求方式不能为空", trigger: "blur" }],
    frontpath: [{ required: true, message: "前端路由不能为空", trigger: "blur" }],
    icon: [{ required: true, message: "菜单图标不能为空", trigger: "blur" }],
    order: [{ required: true }]
  }
})

// 减去头部高度、标签高度、内边距高度
let h = windowHeight.value - 64 - 44 - 112
// 树状、级联组件配置
const defaultProps = {
  children: "child",
  label: "name",
  value: "id",
  checkStrictly: true,
  emitPath: false
}
// 添加子菜单
const addChild = id => {
  // 显示弹窗
  handleCreate()
  form.rule_id = id
  form.status = 1
}
</script>

<template>
  <el-card shadow="never">
    <ListHeader @refresh="getData" @create="handleCreate" />
    <div class="tree" :style="{ height: `${h}px` }">
      <el-tree node-key="id" :data="tableData" :props="defaultProps" v-loading="loading" :default-expanded-keys="defaultExpandedKeys">
        <template #default="{ data }">
          <div class="tree-body">
            <el-tag size="small" :type="data.menu ? '' : 'info'">
              {{ data.menu ? "菜单" : "权限" }}
            </el-tag>
            <el-icon :size="16" v-if="data.icon">
              <component :is="data.icon" />
            </el-icon>
            <span>{{ data.name }}</span>
            <div class="tree-body-actions">
              <el-switch :modelValue="data.status" size="small" :active-value="1" :inactive-value="0" style="--el-switch-on-color: #13ce66" @change="handleStatusChange($event, data)" @click.stop />
              <span class="actions-icon">
                <el-icon :size="16" @click.stop="handleEdit(data)">
                  <Edit />
                </el-icon>
                <el-icon :size="16" @click.stop="addChild(data.id)">
                  <Plus />
                </el-icon>
                <el-popconfirm :title="data.menu ? '是否要删除该菜单？' : '是否要删除该权限？'" confirmButtonText="确认" cancelButtonText="取消" @confirm="handleDelete(data.id, MouseEvent)">
                  <template #reference>
                    <el-icon :size="16">
                      <Close />
                    </el-icon>
                  </template>
                </el-popconfirm>
              </span>
            </div>
          </div>
        </template>
      </el-tree>
    </div>
    <FormDialog ref="dialogRef" :width="50" :title="dialogTitle" @submit="handleSubmit" @close="resetForm">
      <el-form :model="form" ref="formRef" :rules="rules" :inline="false" label-width="90px">
        <el-form-item label="上级菜单" prop="rule_id">
          <el-cascader v-model="form.rule_id" :options="options" :props="defaultProps" placeholder="请选择上级菜单" />
        </el-form-item>
        <el-form-item label="菜单/规则" prop="menu">
          <el-radio-group v-model="form.menu">
            <el-radio :label="1" border>菜单</el-radio>
            <el-radio :label="0" border>规则</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="菜单名称" prop="name">
          <el-input v-model="form.name" placeholder="请输入菜单名称" clearable />
        </el-form-item>
        <el-form-item class="icon" label="菜单图标" prop="icon" v-if="form.menu === 1">
          <IconSelect v-model="form.icon" />
        </el-form-item>
        <el-form-item label="前端路由" prop="frontpath" v-if="form.menu === 1 && form.rule_id > 0">
          <el-input v-model="form.frontpath" placeholder="请输入前端路由" clearable />
        </el-form-item>
        <el-form-item label="后端规则" prop="condition" v-if="form.menu === 0">
          <el-input v-model="form.condition" placeholder="请输入后端规则" clearable />
        </el-form-item>
        <el-form-item label="请求方式" prop="method" v-if="form.menu === 0">
          <el-select v-model="form.method" placeholder="请选择请求方式">
            <el-option v-for="i in ['GET', 'POST', 'PUT', 'DELETE']" :key="i" :label="i" :value="i" />
          </el-select>
        </el-form-item>
        <el-form-item :label="form.menu == 1 ? '菜单排序' : '规则排序'" prop="order">
          <el-input-number v-model="form.order" :min="0" :max="1000" />
        </el-form-item>
      </el-form>
    </FormDialog>
  </el-card>
</template>

<style lang="scss" scoped>
.el-card {
  border: 0;
  .tree {
    overflow: auto;
    :deep(.el-tree-node__content) {
      padding: 10px 0;
    }
    &-body {
      display: flex;
      flex: 1;
      padding-right: 8px;
      .el-tag {
        margin-right: 4px;
      }
      .el-icon {
        padding: 0 10px;
      }
      .el-switch {
        margin: 0 16px;
      }
      &-actions {
        margin-left: auto;
        .actions-icon {
          min-width: 84px;
        }
      }
    }
  }
  :deep(.el-cascader) {
    width: 100%;
  }
  :deep(.icon-select) {
    width: 100%;
  }
}
::-webkit-scrollbar {
  width: 0;
}

@media screen and (max-width: 375px), screen and (max-width: 414px) {
  .el-card {
    padding-bottom: 0;
    .el-tree {
      width: 90vw;
    }
    .el-icon {
      padding: 0 4px !important;
      &:last-child {
        padding-right: 0 !important;
      }
    }
    :deep(.el-card__body) {
      padding-left: 0;
      padding-right: 0;
    }
    :deep(.el-dialog--center) {
      min-width: 80% !important;
      max-width: 80% !important;
    }
    .el-switch {
      margin: 0 4px;
    }
  }
}
</style>
